Java JavaScript Python C# C C++ Go Kotlin PHP Swift R Ruby TypeScript Scala SQL Perl rust VisualBasic Matlab Julia

Encapsulation → Property decorators

Encapsulation

Property decorators

Property Decorators in Python

Python's `@property`, `@setter`, and `@deleter` decorators provide a powerful mechanism for managing attribute access in classes. They allow you to control how attributes are read, written, and deleted, offering a cleaner and more robust way to handle data encapsulation compared to simply using public instance variables. Let's explore each in detail with examples.

1. `@property` (Getter)

The `@property` decorator transforms a method into a read-only attribute. It defines how an attribute's value is retrieved. This separates the data's retrieval logic from the attribute's access, enhancing code organization and maintainability.
Python `@property` (Getter) example class Circle: def __init__(self, radius): self._radius = radius # Using _radius indicates a "protected" attribute @property def radius(self): """Getter for the radius attribute.""" print("Getting radius...") #Demonstrates method execution on access return self._radius @property def area(self): """Calculates and returns the circle's area.""" return 3.14159 * self._radius**2 c = Circle(5) print(c.radius) print(c.area) # c.radius = 10 # This would raise an AttributeError because radius is read-only

Output

Getting radius... 5 78.53975
In this example, `radius` is accessed like a regular attribute, but behind the scenes, the `radius()` method is executed. The `area` property demonstrates calculating a derived attribute based on the underlying `_radius`.

2. `@setter` (Setter)

The `@setter` decorator works in conjunction with `@property`. It allows you to define how an attribute's value is modified. This provides validation and controlled updates, preventing accidental or incorrect data assignment.
Python `@setter` (Setter) example class Rectangle: def __init__(self, width, height): self._width = width self._height = height @property def width(self): return self._width @width.setter def width(self, value): if value > 0: self._width = value else: raise ValueError("Width must be positive.") @property def height(self): return self._height @height.setter def height(self, value): if value > 0: self._height = value else: raise ValueError("Height must be positive.") r = Rectangle(10, 5) print(r.width) r.width = 15 print(r.width) try: r.width = -2 except ValueError as e: print(e)

Output

10 15 Width must be positive.
Here, setting `width` triggers the `width.setter` method, ensuring the new value is positive. Error handling enhances robustness.

3. `@deleter` (Deleter)

The `@deleter` decorator defines how an attribute is deleted. This allows for cleanup or other actions when an attribute is removed.
Python `@deleter` (Deleter) example class Employee: def __init__(self, name, salary): self._name = name self._salary = salary @property def name(self): return self._name @name.setter def name(self,value): self._name = value @name.deleter def name(self): print("Deleting employee name...") del self._name emp = Employee("Alice", 60000) print(emp.name) del emp.name #print(emp.name) # This would raise an AttributeError because name has been deleted.

Output

Alice Deleting employee name...
In this case, deleting `emp.name` calls the `name.deleter` method, printing a message before actually deleting the underlying attribute.

In Summary

Property decorators (`@property`, `@setter`, `@deleter`) are essential tools for building robust and well-structured classes in Python. They provide a clean way to manage attribute access, allowing for data validation, controlled modifications, and custom actions during attribute deletion. They promote data encapsulation and improve code readability and maintainability significantly. Remember to use the underscore prefix (`_`) for internal attributes to signal that they shouldn't be accessed directly from outside the class. This is a convention, not enforced by the language itself.

Tutorials